package com.wwinsoft.framework.dao.security;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.springframework.stereotype.Component;

import com.wwinsoft.framework.entity.security.Group;
import com.wwinsoft.framework.entity.security.User;
import com.wwinsoft.modules.orm.hibernate.HibernateDao;
import com.wwinsoft.modules.utils.reflection.ConvertUtils;

/**
 * 角色对象的泛型DAO.
 *
 * @author calvin
 */
@Component
public class GroupDao extends HibernateDao<Group, Long> {

    private static final String QUERY_USER_BY_ROLEID = "select u from User u left join u.groupList r where r.id=?";
    private static final String QUERY_ROLE_BY_TYPE = "select r from Group r where r.type=? order by id";

    // add by sevenSpend 2011-11-26 start -->
    private static final String QUERY_DEPT_LIST = "select r from Group r where r.type=? order by category, id";
    private static final String QUERY_DEPT_BY_PARENTID = "select r from Group r where r.type=? and parentId=? order by id";
    
    private static final String QUERY_DEPT_BY_CATEGORY = "select r from Group r where r.type=?  order by category, id";
    
    private static final String QUERY_ALL_GROUP = "select r from Group r order by id";
    
    // <-- add by sevenSpend 2011-11-28 end
    
    private final static String SELECT_CHILDREN_SQL = "select getDeptChildList(:parentId)";

    private final static String DELETE_CHILDREN_SQL = "delete from Group where FIND_IN_SET(id,:ids)";

    private final static String SELECT_DEPT_ALIAS_SQL = "select deptId from Group where id in (:ids)";

    private final static String SELECT_PARENT_SQL = "select getGroupParentList(:childrenIds)";

    /**
     * 重载函数,因为Role中没有建立与User的关联,因此需要以较低效率的方式进行删除User与Role的多对多中间表.
     */
    @SuppressWarnings("unchecked")
    @Override
    public void delete(Long id) {
        Group group = get(id);
        //查询出拥有该角色的用户,并删除该用户的角色.
        List<User> users = createQuery(QUERY_USER_BY_ROLEID, group.getId()).list();
        for (User u : users) {
            u.getGroupList().remove(group);
        }
        super.delete(group);
    }

    @SuppressWarnings("unchecked")
    public List<Group> getAllRole() {
        Query query = createQuery(QUERY_ROLE_BY_TYPE, Group.TYPE_ROLE);
        return query.list();
    }

    @SuppressWarnings("unchecked")
    public List<Group> getAllDept() {
        Query query = createQuery(QUERY_ROLE_BY_TYPE, Group.TYPE_DEPT);
        return query.list();
    }

    @SuppressWarnings("unchecked")
    public List<Group> getAllGroup() {
        Query query = createQuery(QUERY_ALL_GROUP);
        return query.list();
    }
    
    // add by sevenSpend 2011-11-28 start -->
    /**
     * 获取部门列表
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<Group> getDeptList() {
        Query query = createQuery(QUERY_DEPT_LIST, Group.TYPE_DEPT);
        return query.list();
    }

    /**
     * 根据上级部门ID获取下级部门
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<Group> getDeptByParentId(Long parentId) {
        Query query = createQuery(QUERY_DEPT_BY_PARENTID, Group.TYPE_DEPT, parentId);
        return query.list();
    }
    
    /**
     * 根据部门类型获取部门列表
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<Group> getDeptByCategory() {
        Query query = createQuery(QUERY_DEPT_BY_CATEGORY, Group.TYPE_DEPT);
        return query.list();
    }
    // <-- add by sevenSpend 2011-11-26 end

    public int deleteAllChildrenBySQL(Serializable id) {
        String children = findChildrenByFunc(id);
        Map paraMap = new HashMap();
        paraMap.put("ids", children);
        Query sqlQuery = this.createSQLQuery(DELETE_CHILDREN_SQL, paraMap);
        return sqlQuery.executeUpdate();
    }

    private String findChildrenByFunc(Serializable id) {
        Map paraMap = new HashMap();
        paraMap.put("parentId", id);
        Query sqlQuery = this.createSQLQuery(SELECT_CHILDREN_SQL, paraMap);
        String idList = (String) sqlQuery.uniqueResult();
        return idList;
    }

    private String findParentsByFunc(String children) {
        Map paraMap = new HashMap();
        paraMap.put("childrenIds", children);
        Query sqlQuery = this.createSQLQuery(SELECT_PARENT_SQL, paraMap);
        String idList = (String) sqlQuery.uniqueResult();
        return idList;
    }

    @SuppressWarnings("unchecked")
    public Collection<Long> getParentsByChildren(List<Long> children){
        String childrenStr = StringUtils.join(children, ",");
        String parentsStr = findParentsByFunc(childrenStr);
        Set<Long> parentsList = ConvertUtils.convertSeparatorStringToSet(parentsStr, ",", Long.class);
        for (Iterator<Long> iterator = parentsList.iterator(); iterator.hasNext(); ) {
            Long parent = iterator.next();
            if(children.contains(parent)){
                iterator.remove();
            }
        }
        return parentsList;
    }

    @SuppressWarnings("unchecked")
    public Collection<String> getParentAliasListByChildren(List<Long> children){
        Collection<Long> parentIds= getParentsByChildren(children);
        return getAliasIdList(parentIds);
    }

    @SuppressWarnings("unchecked")
    public Collection<String> getAliasIdList(Collection<Long> ids) {
        if(ids.size()==0){
            return new ArrayList<String>();
        }
        Map paraMap = new HashMap();
        paraMap.put("ids", ids);
        Collection<String> list = find(SELECT_DEPT_ALIAS_SQL,paraMap);
        return list;
    }

    public Group getRoleWithAuthorityFilter(Long id){
         getSession().enableFilter("defaultAuthorityFilter");
         return get(id);
    }

}
